package com.fuyun.microservice.codec;

import com.fuyun.microservice.codec.msg.Header;
import com.fuyun.microservice.codec.msg.Message;
import com.fuyun.microservice.codec.msg.QueryResponseMessage;
import com.fuyun.microservice.utils.BufferUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.util.List;

@Slf4j
@ChannelHandler.Sharable
public class QueryResponseMessageCodec extends MessageToMessageCodec<Message, QueryResponseMessage> {
    private static final int RSPMES_LENGTH = 32;

    @Override
    protected void decode(ChannelHandlerContext ctx, Message msg, List<Object> out) {
        Header header = msg.getHeader();
        if (header.getCommandId() != PacketType.QUERYRESPONSE.getCommandId()) {
            out.add(msg);
            return;
        }

        QueryResponseMessage responseMessage = new QueryResponseMessage(header.getSequenceNo());
        BeanUtils.copyProperties(msg, responseMessage);

        ByteBuf bodyBuffer = Unpooled.wrappedBuffer(msg.getBodyBuffer());
        responseMessage.setResultCode(bodyBuffer.readInt());

        responseMessage.setResultMessage(bodyBuffer.readBytes(RSPMES_LENGTH).toString(BufferUtil.CHARSET_DEFAULT));

        int rspBodyLength = header.getBodyLength() - HeaderCodec.HEADER_LENGTH - BufferUtil.DWORD_LENGTH - RSPMES_LENGTH;
        byte[] rspBytes = BufferUtil.toByteArraySafe(bodyBuffer.readBytes(rspBodyLength));
        String rspBody = new String(rspBytes,BufferUtil.CHARSET_DEFAULT);
        log.debug("resultbody:" + rspBody);
        responseMessage.setResultBody(rspBody);

        ReferenceCountUtil.release(bodyBuffer);
        out.add(responseMessage);
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, QueryResponseMessage msg, List<Object> out) throws Exception {
        byte[] rspBytes =  msg.getResultBody().getBytes(BufferUtil.ENCODE_CHARSET);
        int contentLength = BufferUtil.DWORD_LENGTH + RSPMES_LENGTH + rspBytes.length;

        ByteBuf bodyBuffer = Unpooled.buffer(contentLength);
        bodyBuffer.writeInt(msg.getResultCode());

        byte[] resultMsgBytes = BufferUtil.toFixedBytes(msg.getResultMessage(), RSPMES_LENGTH);
        bodyBuffer.writeBytes(resultMsgBytes);
        bodyBuffer.writeBytes(rspBytes);
        msg.setBodyBuffer(bodyBuffer.array());

        ReferenceCountUtil.release(bodyBuffer);
        out.add(msg);
    }
}
